//
//  YWDetectorFaceController.m
//  YWPhotoEditMaster
//
//  Created by jun peng on 2023/9/7.
//

#import "YWDetectorFaceController.h"

@interface YWDetectorFaceController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)detBtnClick:(UIButton *)sender;



@property (weak, nonatomic) IBOutlet UIView *iconBgView;
@property (weak, nonatomic) UIScrollView *iconScrollView;

@property(nonatomic,strong)UIImage *orginalImage; //一开始原始照片


@end

@implementation YWDetectorFaceController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.imageView.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
    
    [self.imageView addGestureRecognizer:tap];
    
    self.orginalImage = self.imageView.image;
    
    
    
    UIScrollView *scrollView = [[UIScrollView alloc] init];
    [self.iconBgView addSubview:scrollView];
    self.iconScrollView = scrollView;
    
    
}

-(void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    
    self.iconScrollView.frame = self.iconBgView.bounds;
    
}

-(void)tap{
    
     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    
    [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
        NSLog(@"点击取消");
        
    }]];
    
    [alertController addAction:[UIAlertAction actionWithTitle:@"选择相册" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        [self getPhoto];
        
    }]];
    
    [alertController addAction:[UIAlertAction actionWithTitle:@"拍照片" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        [self takePhoto];
    }]];
    
    // 由于它是一个控制器 直接modal出来就好了
    [self presentViewController:alertController animated:YES completion:nil];
    
}



//取相片
-(void)getPhoto{
    // 进入相册
    
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
        
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
        
//        imagePicker.allowsEditing = YES;
        
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        
        imagePicker.delegate = self;

        imagePicker.modalPresentationStyle = 0;
        [self presentViewController:imagePicker animated:YES completion:^{
            
            YWLog(@"打开相册");
            
        }];
        
    }
    else{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"错误" message:@"请让APP访问您的相册" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
        [alert addAction:action];
        
        [self presentViewController:alert animated:YES completion:nil];
    }
    
}

//拍照
-(void)takePhoto{
    // 进入相册
    
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
        
//        imagePicker.allowsEditing = YES;
        
        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
        
        imagePicker.delegate = self;
        
        imagePicker.modalPresentationStyle = 0;
        [self presentViewController:imagePicker animated:YES completion:^{
            
            YWLog(@"打开相机");
            
        }];
        
    }
    else{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"错误" message:@"相机不可用" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
        [alert addAction:action];
        
        [self presentViewController:alert animated:YES completion:nil];
    }
    
}

#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    //    获取图片
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    
    image = [self pressImage:image];//压缩图片防止内存过大而崩溃
    
    image = [self dealImage:image]; //系统拍照的照片含有方向属性所以要处理
    
    self.orginalImage = image;
    
//    image = [self rotateImage:image rotation:0]; //通过压缩完图片后，方向的枚举肯定是0，所以不需要写上面dealImage的处理方法、直接写旋转0度就行、但假如你想完整表达就写上面的dealImage处理方法
    
    self.imageView.image = image;
    
    //    获取图片后返回
    [picker dismissViewControllerAnimated:YES completion:nil];
}

//其它相机或者网络图片或者截屏什么的imageOrientation属性默认都是0、而而系统相机的image的imageOrientation有多个方向、所以导致人面检测画框位置不准
-(UIImage *)dealImage:(UIImage *)image{
    
    //要转为png (你不转png也行、不过你转了png后显示就能露出它的问题破绽)
    NSData *imageData = UIImagePNGRepresentation(image);
    
    UIImage *newImage = [UIImage imageWithData:imageData];
    
    YWLog(@"%ld",image.imageOrientation);
    YWLog(@"%ld",newImage.imageOrientation); //因为转为png后无论什么方向imageOrientation都变为0了

    switch (image.imageOrientation) { //通过原来的image判断方向
        case UIImageOrientationUp:
        {
            newImage = [self rotateImage:newImage rotation:0];
        }
            break;
        case UIImageOrientationDown:
        {
            
            newImage = [self rotateImage:newImage rotation:M_PI];
        }
            break;
        case UIImageOrientationLeft:
        {
            newImage = [self rotateImage:newImage rotation:M_PI_2];
        }
            break;
        case UIImageOrientationRight:
        {
            
            newImage = [self rotateImage:newImage rotation:-M_PI_2];
        }
            break;

        default:
            break;
    }
    
    return  newImage;
}

//这种强制转换方向也会导致人面检测画框位置不准:UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];
//所以用下面的方法
-(UIImage *)rotateImage:(UIImage *)newImage rotation:(CGFloat)angle{
    
    CIImage *ciImage = [CIImage imageWithCGImage:newImage.CGImage];
    CGAffineTransform transform = CGAffineTransformMakeRotation(angle); //-M_PI_2
    CIImage *rotatedImage = [ciImage imageByApplyingTransform:transform];
    CGRect extent = [rotatedImage extent];
    CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer: @NO}];
    CGImageRef cgImage = [context createCGImage:rotatedImage fromRect:extent];
    UIImage *adjustedImage = [UIImage imageWithCGImage:cgImage];
    
    return  adjustedImage;
    
}

//压缩图片防止内存过大而崩溃
-(UIImage *)pressImage:(UIImage *)image{
    
    CGSize originalSize = image.size;
    CGFloat newWidth = 0;
    CGFloat newHeight = 0;
    
    if (originalSize.width > originalSize.height) {
        
        newWidth = 256.0;
        newHeight = originalSize.height / originalSize.width * newWidth;
    }else {
        
        newHeight = 256.0;
        newWidth = originalSize.width / originalSize.height * newHeight;
    }
    
    CGSize size = CGSizeMake(newWidth, newHeight);
    
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    
    
    //从上下文当中取出一张图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    //关闭上下文
    UIGraphicsEndImageContext();
    
    return newImage;
}

//    CIDetectorTypeFace 人面识别 (只能真机测试)
//    CIDetectorTypeRectangle 矩形识别
//    CIDetectorTypeQRCode 二维码识别
//    CIDetectorTypeText 文字识别

- (IBAction)detBtnClick:(UIButton *)sender {
    
    //移除scrollView上面的icon
    [self removeIconViewFromScrollView];
    
    // .1 获取需要识别的图片
    UIImage *image = self.orginalImage;
    CIImage *imageCI = [[CIImage alloc] initWithImage:image];
    
    // 开始识别
    // 1. 创建一个二维码探测器
    CIDetector *dector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}];
    
    // 2. 直接探测二维码特征
    NSArray *features = [dector featuresInImage:imageCI];
    
    
    for (CIFeature *feature in features) {
        CIFaceFeature *faceFeature = (CIFaceFeature *)feature;
        
        self.imageView.image = [self drawFrameWithImage:self.imageView.image feature:faceFeature];
        
        //添加人面icon到ScrollView
        [self addIconViewToScrollViewWithImage:self.orginalImage faceFeature:faceFeature];
    }
    
    
}

//移除scrollView上面的icon
-(void)removeIconViewFromScrollView{
    NSArray *iconArray = self.iconScrollView.subviews;
    [iconArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        UIImageView *icon = (UIImageView *)obj;
        [icon removeFromSuperview];
    }];
    
}


//添加人面icon
-(void)addIconViewToScrollViewWithImage:(UIImage *)image faceFeature:(CIFaceFeature *)faceFeature{
    
    //可以确定feature的size在转换坐标系、size不受坐标系影响
    CGSize faceFeatureSize = faceFeature.bounds.size;
    
    CGSize imageSize = image.size;
    
    //faceFeatureSize是确定了你要生成图片的大小
    UIGraphicsBeginImageContextWithOptions(faceFeatureSize, NO, 0);
    
    
    //裁剪区域就是裁剪的大小、所以是CGRectMake(0, 0, bounds.size.width, bounds.size.height)
    //把ImageV绘制到上下文之前,设置一个裁剪区域
    CGRect rect = CGRectMake(0, 0, faceFeatureSize.width, faceFeatureSize.height);
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:rect];//裁剪的是圆形
//    UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:rect];
    [clipPath addClip];
    
    
    
//    因为上下文不是整张image的size,而是很小的头像的size，这时假如你把上下文坐标系上下颠倒就把头像区域反转而已、所以我不能用转换坐标系方法、而是手动计算Y值
    
        
    CGRect faceFeatureBounds = faceFeature.bounds;
    
    //不能用上面的renderInContext、只能用drawAtPoint、且x和y是负数确定位置
    CGFloat tailorX = -faceFeatureBounds.origin.x;
    CGFloat y = imageSize.height - faceFeatureSize.height - faceFeatureBounds.origin.y;
    CGFloat tailorY = -y;
    CGPoint tailorPoint = CGPointMake(tailorX, tailorY);
    [image drawAtPoint:tailorPoint];
    
    //.从上下文当中生成 一张图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    //关闭上下文
    UIGraphicsEndImageContext();
    
    // ---------------------------
    
    UIImageView *iconView = [[UIImageView alloc] init];
    iconView.image = newImage;
    CGFloat margin = 10;
    CGFloat height = self.iconBgView.height;
    CGFloat width = height;
    CGFloat iconY = 0;
    CGFloat iconX = margin + (margin + width) * self.iconScrollView.subviews.count;
    iconView.frame = CGRectMake(iconX, iconY, width, height);
    [self.iconScrollView addSubview:iconView];
    
}




//画框框
-(UIImage *)drawFrameWithImage:(UIImage *)image feature:(CIFaceFeature *)feature{
    
    CGSize size = image.size;
    
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    
    //转换坐标系（上下颠倒）因为写在了中间这里、所以上下颠倒对下面绘制路径有效果、对上面的image drawInRect无效果
    CGContextRef ctx =  UIGraphicsGetCurrentContext();
    CGContextScaleCTM(ctx, 1, -1); //Y轴Scale写-1相当于镜像倒立
    CGContextTranslateCTM(ctx, 0, -size.height); //再向上移动回height那么多
    
    // 绘制路径
    CGRect bounds = feature.bounds;
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:bounds];
    [[UIColor redColor] set];
    path.lineWidth = 6;
    [path stroke];
    
    
    //从上下文当中取出一张图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    //关闭上下文
    UIGraphicsEndImageContext();
    
    return newImage;;
    
    
}


@end
